package Nonogram;

/**
 * GridArray
 * @author Rachel Wedewer, Mollie Burkle, Kriste nNielsen
 * Date Modified: 4/30/2014
 * 
 * This class represents the state of the puzzle board the user and solver interact with.
 * It controls changing the states of the cell on the board.  Other helpful methods were added to
 * this object for the solver and ErrorDetection.
 *  
 */
public class GridArray {
    
	private int[][] grid;  //Cols, rows
	private Data data;
	
	public GridArray(int size, Data data){
	
		grid = new int[size][];
		this.data = data;
		for (int i = 0; i < grid.length; i++){
			grid[i] = new int[size];
		}
		setGridAllUnknownState();
	}
	
	public void setGridAllUnknownState(){
		for (int i = 0; i < grid.length; i++){
			for (int x = 0; x <grid.length; x++){
				grid[i][x] = -1;
			}
		}
	}
	
	public int getCellValue(int row, int col){
		return grid[row][col];
	}
	
	public void setCellUnknownState(int row, int col){
		grid[row][col] = -1;
	}
	
	public void setCellBlankState(int row, int col){
		grid[row][col] = 0;
		checkPuzzleWhenNoUnknownsLeft();
		}
	
	public void setCellFillState(int row, int col){
		grid[row][col] = 1;
		checkPuzzleWhenNoUnknownsLeft();
		}
	
	public boolean gridWithNoUnknowns(){
		for (int i = 0; i < grid.length; i++){
			for (int x = 0; x <grid.length; x++){
				if (grid[i][x] == -1){
					return false;
				}
			}
		}
		
		return true;
	}
	
	
	

	public boolean allCellsInRowMarked(int rowLine){
		for (int x = 0; x <grid.length; x++){
				if (grid[rowLine][x] == -1){
					return false;
				}
		}	
		return true;
	}
	
	public boolean allCellsInColMarked(int colLine){
		for (int x = 0; x <grid.length; x++){
				if (grid[x][colLine] == -1){
					return false;
				}
		}	
		return true;
	}
	
	//Getters
	public int[][] getGrid() {
		return grid;
	}

    public int[] getRow(int row) {
        int[] new_Row = new int[grid.length];
        for(int i = 0; i < grid.length; i++) {
            new_Row[i] = grid[row][i];
        }
        return new_Row;        
    }
    
    public int[] getCol(int col) {
        int[] new_Col = new int[grid.length];
        for(int i = 0; i < grid.length; i++) {
            new_Col[i] = grid[i][col];
        }
        return new_Col;        
    }
	
	//For Debugging
	public void printGrid(){
		String line = "";
		
		for (int i = 0; i < grid.length; i++){
			for (int x = 0; x <grid.length; x++){
				line = line + grid[i][x]+", ";
			}
			line = "";
		}
	}
	
	
	/////For Solver and ErrorDetection
	public void markRowCellRange(int state, int line, int start, int end){
		//state most be equal to 0 or 1
		//Line is the row being altered
		//Start of range
		//End of range
		
		for (int x = start; x < (end-start) +1; x++){
			grid[line][x] = state;
		}
		
	}
	
	public void markColCellRange(int state, int line, int start, int end){
		//state most be equal to 0 or 1
		//Line is the row being altered
		//Start of range
		//End of range
		
		for (int x = start; x < (end-start) +1; x++){
			grid[x][line] = state;
		}
	}

	public void checkPuzzleWhenNoUnknownsLeft(){
		if (gridWithNoUnknowns()) {
		data.checkPuzzle();
		
		}
	}
	
    
    public int getNumberFillState(boolean isRow, int state, int lineNum) {
        int count = 0;
        int[] lineToTest;
        if (isRow) {
                lineToTest = getRow(lineNum);
        }
        else {
                lineToTest = getCol(lineNum);
        }
        for (int i = 0; i < lineToTest.length; i++) {
                if (lineToTest[i] == state) {
                        count++;
                }
        }
        return count;
    }
  
    
     	/**
	 	* Returns the first index of the desired state
	 	* @param isRow True if the line you want is a row, otherwise false
		* @param state Which state you wish to test for
	 	* @param lineNum
	 	* @param startIndex
	 	* @return First index of the wanted state
	 	*/
		public int getFirstCellState(boolean isRow, int state, int lineNum, int startIndex) {
	 	int[] lineToTest;
	 	if (isRow) {
	 		lineToTest = getRow(lineNum);
	 	}
	 	else {
	 		lineToTest = getCol(lineNum);
	 	}
	 	for (int i = startIndex; i < lineToTest.length; i++) {
	 		if (lineToTest[i] == state) {
	 			return i;
	 	}
	 	}
	 		return -1;
		}
                public int getLastCellState(boolean isRow, int state, int lineNum, int startIndex) {
                    int[] lineToTest;
                    if (isRow) {
                        lineToTest = getRow(lineNum);
                    }
                    else {
                        lineToTest = getCol(lineNum);
                    }
                    for (int i = startIndex; i >= 0; i--) {
                        if (lineToTest[i] == state) {
                            return i;
                        }
                    }
                    return -1;
                }
		
		// returns the number of isolated black marked cell segments there are in a given
		// partially completed line
		public int getNumBlocksMarked(int[] line) {
			int delta = 0;
			int counter = 0;
			
			for (int i = 0; i < line.length; i++) {
				if (line[i] == 1) {
					delta = 1;
				}
				else {
					delta = 0;
				}
				if (delta > 0) {
					counter++;
				}
			}
			return counter;		
		}
		
		
		public int getMinNumClue(int[] clues){
			int min = data.getBoardsize();
			for (int i =0; i < clues.length; i++){
				if (clues[i] < min){
					min = clues[i];
				}
			}
			return min;
		} 
}
